const RESERVED_PROPS = {//标记 React 内部使用的 “保留属性”。这些属性不会作为普通属性传递给组件
    key: true,
    ref: true,
    __self: true,
    __source: true,
};
// key：用于列表渲染时的 diff 算法，标识元素唯一性，优化重渲染性能。
// ref：用于获取真实 DOM 元素或组件实例的引用。
// __self：开发环境下记录当前组件的上下文（调试用）。
// __source：开发环境下记录组件在源码中的位置（如文件名、行号，调试用）

export function createElement(type, config, ...children) {
    //     - type : 元素类型如 'div' 等 HTML 标签名，或 React 组件（函数 / 类组件））
    // - config : 包含元素属性的对象
    // - ...children : 剩余参数，收集所有子元素（可以是文本、其他 React 元素、数组等）
    let propName;

    // Reserved names are extracted
    const props = {};//用于存储最终传递给组件的 “普通属性”，开发者定义的普通属性

    // 第一段
    let key = '' + config.key;
    let ref = config.ref;
    let self = config.__self;
    let source = config.__source;

    // 第二段,普通属性提取阶段 ：从配置中分离保留属性和普通属性
    for (propName in config) {
        if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
            props[propName] = config[propName];
        }
    }

    // 第三段
    props.children = children;
    // 将收集到的所有子元素（...children）作为 props.children 存入 props。
    // 这就是为什么在 React 组件中可以通过 props.children 访问子元素
    // （如 <Parent>子元素</Parent> 中，Parent 组件可通过 props.children 获取 “子元素”）。

    // 第四段，属性处理阶段 ：应用默认属性，将组件的默认属性提取出来放入props中
    if (type && type.defaultProps) {//type是组件类型，有可能是父组件或子组件，如果是父组件，则有defaultProps属性
        const defaultProps = type.defaultProps;
        for (propName in defaultProps) {
            if (props[propName] === undefined) {
                props[propName] = defaultProps[propName];
            }
        }
    }

    // 第五段,元素创建阶段 ：调用 ReactElement 构造函数创建并返回最终的虚拟 DOM 元素
    return ReactElement(
        type,
        key,
        ref,
        self,
        source,
        ReactCurrentOwner.current,//当前元素的 “所有者” 组件（React 内部用于追踪组件层级关系）。
        props,
    );
}